home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d21 / dvmulti.arc / SUPER.C < prev   
C/C++ Source or Header  |  1989-10-25  |  21KB  |  837 lines

  1. /* Supervisor program for DESQview tests
  2.  
  3.     1989    MIPS Magazine / Mark Mallett
  4.  
  5. */
  6.  
  7. #include <stdio.h>
  8. #include <dvapi.h>
  9. #include "dvmulti.h"
  10.  
  11. /* Macro to ring the alarm */
  12. #define    beep()        api_sound( 1000, 5 )
  13.  
  14.  
  15. /* Fields in the task definition menu */
  16. #define    TDF_TSIZE    1        /* Task size */
  17. #define    TDF_SLEEP    2        /* Sleep time */
  18. #define    TDF_READ    3        /* I/O read */
  19. #define    TDF_WRITE    4        /* I/O write */
  20. #define    TDF_SEQ        5        /* Sequential I/O */
  21. #define    TDF_RAND    6        /* Random I/O */
  22. #define    TDF_FSIZE    7        /* File size */
  23. #define    TDF_XSIZE    8        /* Transfer size */
  24. #define    TDF_BUFC    9        /* Buffers */
  25. #define    TDF_IOC        10        /* IO count */
  26. #define    TDF_LOOPC    11        /* CPU Loops */
  27. #define    TDF_TASKC    12        /* Tasks */
  28. #define    TDF_ABORT    13        /* Abort */
  29. #define    TDF_CONFIRM    14        /* Confirmation */
  30.  
  31. #define    TDF_FIELDC    (14+1)        /* Number of fields including
  32.                        a dummy #0 */
  33.  
  34.  
  35. /* Fields in the "go" menu */
  36. #define    GO_TIME        1        /* Time for the test */
  37. #define    GO_FILENAME    2        /* File for results */
  38. #define    GO_ABORT    3        /* Abort */
  39. #define    GO_CONFIRM    4        /* Confirmation */
  40.  
  41. #define    GO_FIELDC    (4+1)        /* # of fields, including #0 */
  42.  
  43.  
  44.  
  45. typedef                    /* Keeps track of each SLAVE */
  46.   struct {
  47.     ULONG    sd_apphan;        /* Application handle */
  48.     ULONG    sd_malhan;        /* Mailbox handle */
  49.     char    sd_readyF;        /* Ready to go */
  50.     char    sd_doneF;        /* Done; received report. */
  51.     CNMSG    sd_cnmsg;        /* Configuration message */
  52.     RSMSG    sd_rsmsg;        /* Report/status message */
  53.   } SLAVEDATA;
  54.  
  55.  
  56. /* External routines */
  57.  
  58. extern    long    atol();
  59.  
  60.  
  61. /* Local Variables */
  62.  
  63. static    char    Gofile[50];        /* Filename for report */
  64. static    ULONG    Gotime;            /* Execution time */
  65. static    ULONG    Kbd_go;            /* Keboard object for Go menu */
  66. static    ULONG    Kbd_main;        /* Main keyboard object handle */
  67. static    ULONG    Kbd_tdef;        /* Task def keyboard handle */
  68. static    ULONG    Mal_main;        /* Main mailbox */
  69. static    ULONG    Tim_main;        /* Main timer */
  70. static    ULONG    Win_go;            /* GO menu window */
  71. static    ULONG    Win_main;        /* Main window */
  72. static    ULONG    Win_tdef;        /* Task def window handle */
  73.  
  74. static    int    SlaveC;            /* Number of defined slaves */
  75. static    SLAVEDATA Slavetbl[MAXSLAVES];    /* Control info for slaves */
  76.  
  77. static    char    Tdf_fields[TDF_FIELDC][20]; /* Task def field values */
  78. static    char    Tdf_valid[TDF_FIELDC];        /* Valid field indicators */
  79.  
  80.  
  81.  
  82. static    char    Gomenu[] = "\
  83. \n\
  84.  -Execution-\n\
  85. \n\
  86.  Period(seconds):\n\
  87.  Filename:\n\
  88. \n\
  89.  Press RETURN when done\n\
  90.  Press ESC to abort ";
  91.  
  92.  
  93.  
  94. static    char    Goftab[] =    {
  95.     ftab( GO_FIELDC-1,\
  96.          FTH_KEYSELECT+FTH_MODIFIED+FTH_AUTORESET,\
  97.          0, 0, ATTR_REVERSE, 2),
  98.     3, 18, 3, 27, FTE_INPUT, FTE_RIGHTJUST+FTE_CLEARDFLT, 0, 0,
  99.     4, 12, 4, 31, FTE_INPUT, FTE_CLEARDFLT, 0, 0,
  100.     1, 0, 0, 0, FTE_SELECT, 27, 1, 0,
  101.     1, 0, 0, 0, FTE_SELECT, 13, 1, 0
  102.                 };
  103.  
  104.  
  105.  
  106. static    char    Prgmenu[] = "\
  107. \n\
  108.   -Super-\n\
  109. \n\
  110.   Define Task    DT\n\
  111.   Go             GO\n\
  112.   Exit           EX ";
  113.  
  114. static    char    Prgftab[] =    {
  115.     ftab( 5, FTH_KEYSELECT+FTH_MODIFIED, 0, 0, ATTR_REVERSE, 1 ),
  116.     1, 17, 1, 18, FTE_OUTPUT, 0, 0, 0,
  117.     3, 1, 3, 19, FTE_SELECT, 'D', 1, 'T',
  118.     4, 1, 4, 19, FTE_SELECT, 'G', 1, 'O',
  119.     5, 1, 5, 19, FTE_SELECT, 'E', 1, 'X',
  120.     3, 0, 0, 0, FTE_SELECT, 27, 1, 0
  121.                 };
  122.  
  123.  
  124.  
  125. static    char    Tdefmenu[] = "\
  126. \n\
  127.  -Configure-\n\
  128. \n\
  129.  Task Size:\n\
  130.  Sleep:\n\
  131.  Disk IO:  READ WRITE SEQ RAND\n\
  132.      File Size (KB):           Transfer Size:\n\
  133.      Buffers:                  Count:\n\
  134. \n\
  135. CPU\n\
  136.    Loops:                  RETURN when done\n\
  137.    Tasks:                  ESC to abort";
  138.  
  139.  
  140. static    char    Tdefftab[] =    {
  141.     ftab( TDF_FIELDC-1,\
  142.          FTH_KEYSELECT+FTH_MODIFIED+FTH_AUTORESET,\
  143.          0, 0, ATTR_REVERSE, 2),
  144.     3, 12, 3, 16, FTE_INPUT, FTE_RIGHTJUST+FTE_CLEARDFLT, 0, 0,
  145.     4, 12, 4, 16, FTE_INPUT, FTE_RIGHTJUST+FTE_CLEARDFLT, 0, 0,
  146.     5, 11, 5, 14, FTE_SELECT, 0, 1, 0,
  147.     5, 16, 5, 20, FTE_SELECT, 0, 1, 0,
  148.     5, 22, 5, 24, FTE_SELECT, 0, 1, 0,
  149.     5, 26, 5, 29, FTE_SELECT, 0, 1, 0,
  150.     6, 20, 6, 26, FTE_INPUT, FTE_RIGHTJUST+FTE_CLEARDFLT, 0, 0,
  151.     6, 45, 6, 51, FTE_INPUT, FTE_RIGHTJUST+FTE_CLEARDFLT, 0, 0,
  152.     7, 20, 7, 26, FTE_INPUT, FTE_RIGHTJUST+FTE_CLEARDFLT, 0, 0,
  153.     7, 45, 7, 51, FTE_INPUT, FTE_RIGHTJUST+FTE_CLEARDFLT, 0, 0,
  154.     10, 11, 10, 19, FTE_INPUT, FTE_RIGHTJUST+FTE_CLEARDFLT, 0, 0,
  155.     11, 11, 11, 19, FTE_INPUT, FTE_RIGHTJUST+FTE_CLEARDFLT, 0, 0,
  156.     1, 0, 0, 0, FTE_SELECT, 27, 1, 0,
  157.     1, 0, 0, 0, FTE_SELECT, 13, 1, 0
  158.                 };
  159.  
  160. main()
  161. {
  162.     int        version;    /* Version of current dv */
  163.  
  164.     version = api_init();
  165.     if ( version < DVVER ) {
  166.     fprintf( stderr, "DESQview version %d.%02d or later required.\n",
  167.           DVVER/256, DVVER%256 );
  168.     }
  169.     else {
  170.     api_level( DVVER );
  171.     super();
  172.     }
  173.  
  174.     if ( version != 0 )
  175.     api_exit();
  176. }
  177.  
  178.  
  179.  
  180. /* The functional main program of the supervisor program.  Called after
  181.    DESQview environment is established. */
  182.  
  183. super()
  184. {
  185.     char        field;        /* Field selected */
  186.     char        done;
  187.     int        kbdL;        /* Length of keyboard input */
  188.     char        *kbdP;        /* Ptr to keyboard buffer */
  189.  
  190.     /* Get handles to main window, keyboard, mailbox, and a timer. */
  191.     Win_main = win_me();
  192.     Kbd_main = key_me();
  193.     Mal_main = mal_me();
  194.     Tim_main = tim_new();
  195.  
  196.     /* Set logical and physical window sizes for main window */
  197.     win_resize( Win_main, 7, 21 );
  198.     win_lsize( Win_main, 7, 21 );
  199.  
  200.     /* Position and set to use logical attributes */
  201.     win_origin( Win_main, 0, 0 );
  202.     win_move( Win_main, 5, 10 );
  203.     win_logattr( Win_main, 1 );
  204.     win_attr( Win_main, 1 );
  205.  
  206.     /* Enable field mode, no hardware cursor */
  207.     key_subfrom( Kbd_main, KBF_CURSOR );
  208.     key_addto( Kbd_main, KBF_FIELD );
  209.  
  210.     /* Throw up the main menu */
  211.     win_swrite( Win_main, &Prgmenu[0] );
  212.     win_stream( Win_main, &Prgftab[0] );
  213.     win_redraw( Win_main );
  214.     
  215.     /* Loop processing menu items */
  216.     for( done = FALSE; !done; ) {
  217.     key_read( Kbd_main, &kbdP, &kbdL );
  218.     field = *kbdP;
  219.     fld_reset( Win_main );
  220.     win_redraw( Win_main );
  221.  
  222.     /* Process the field */
  223.     switch( field ) {
  224.         case 2:            /* Task definition */
  225.         if ( SlaveC == MAXSLAVES )
  226.             beep();        /* All tasks defined */
  227.         else
  228.             task_def();
  229.         break;
  230.  
  231.         case 3:            /* Go */
  232.         if ( SlaveC == 0 )
  233.             beep();        /* No slaves configured */
  234.         else {
  235.             go();        /* Run the thing */
  236.             done = TRUE;    /* And we're done. */
  237.         }
  238.         break;
  239.  
  240.         case 4:            /* Real exit */
  241.         case 5:            /* Dummy exit */
  242.         done = TRUE;
  243.         break;
  244.  
  245.         default:
  246.         break;
  247.     }
  248.     }
  249. }
  250.  
  251.  
  252.  
  253. /* Go -- run the suite of slaves */
  254. go()
  255. {
  256.     int        i;
  257.     int        taskN;        /* Task number */
  258.     int        readyC;        /* Ready count */
  259.     int        doneC;        /* Done count */
  260.     int        msgcode;    /* Message code */
  261.     int        msgL;        /* Length of received message */
  262.     char        *msgP;        /* ptr to input message */
  263.     ULONG        sendtsk;    /* Sending task */
  264.     DVP        sdvp;        /* Descriptor for slave */
  265.     SLAVEDATA    *slaveP;    /* Ptr to slave block */
  266.  
  267.     /* Get report & execution parameters */
  268.     if ( !getgo() )
  269.     return;
  270.  
  271.     /* Fire up each task */
  272.     for( taskN = 0, slaveP = &Slavetbl[0]; taskN < SlaveC;
  273.          ++taskN, ++slaveP ) {
  274.     /* Clear out the dvp */
  275.     memset( &sdvp, 0, sizeof( DVP ) );
  276.  
  277.     /* Fill in the dvp to run a copy of slave */
  278.     sprintf( &sdvp.dvp_title[0], "SLAVE #%d", taskN );
  279.     memset( &sdvp.dvp_title[strlen(&sdvp.dvp_title[0])], ' ',
  280.           30-strlen(&sdvp.dvp_title[0]) );
  281.     sdvp.dvp_minmem = atol( &Tdf_fields[TDF_TSIZE][0] );
  282.     sdvp.dvp_maxmem = sdvp.dvp_minmem + 20;
  283.     strcpy( &sdvp.dvp_execcmd[0], "SLAVE.EXE" );
  284.     sdvp.dvp_drive = TESTDRIVE;
  285.     strcpy( &sdvp.dvp_dir[0], TESTDIR );
  286.     sdvp.dvp_tpages = 1;
  287.     sdvp.dvp_firstvec = 0;
  288.     sdvp.dvp_lastvec = 0xff;
  289.     sdvp.dvp_lrows = 2;
  290.     sdvp.dvp_lcols = 15;
  291.     sdvp.dvp_irow = ((taskN*4)%20) +1;
  292.     sdvp.dvp_icol = ((taskN*4)/20) * 17 +1;
  293.     sdvp.dvp_ctlbyte1 = 1;        /* Swappable */
  294.     sdvp.dvp_ctlbyte2 = 0;
  295.     sdvp.dvp_swappable = 1;
  296.     sdvp.dvp_eclose = 1;
  297.     sdvp.dvp_rsv3 = 1;        /* Must be 1 */
  298.     sdvp.dvp_prows = sdvp.dvp_lrows;
  299.     sdvp.dvp_pcols = sdvp.dvp_lcols;
  300.     sdvp.dvp_iniscrmode = 0xff;
  301.  
  302.     /* Start up the app */
  303.     slaveP->sd_apphan = app_start( &sdvp, sizeof(DVP) );
  304.     if ( slaveP->sd_apphan == 0 ) {
  305.         beep();
  306.         break;
  307.     }
  308.     slaveP->sd_readyF = FALSE;
  309.     slaveP->sd_doneF = FALSE;
  310.     if ( ( slaveP->sd_malhan = mal_of( slaveP->sd_apphan ) ) == 0 ) {
  311.         beep();
  312.         break;
  313.     }
  314.  
  315.     /* Send configuration data to the slave */
  316.     mal_addto( slaveP->sd_malhan, &slaveP->sd_cnmsg, sizeof(CNMSG),
  317.                 MSG_CONFIG );
  318.     }
  319.  
  320.     /* Wait for READY responses from all the slaves */
  321.     for( ; ; ) {
  322.     msgcode = mal_read( Mal_main, &msgP, &msgL );
  323.     if ( msgcode == MSG_READY ) {
  324.         sendtsk = mal_addr( Mal_main );
  325.         for( i = 0, slaveP = &Slavetbl[0], readyC = 0;
  326.              i < SlaveC; ++i, ++slaveP ) {
  327.         if ( sendtsk == slaveP->sd_apphan )
  328.             slaveP->sd_readyF = TRUE;
  329.         if ( slaveP->sd_readyF )
  330.             ++readyC;
  331.         }
  332.  
  333.         /* If all tasks ready, proceed to next phase */
  334.         if ( readyC == SlaveC )
  335.         break;
  336.     }
  337.     }
  338.  
  339.     /* Make sure we're the foreground */
  340.     win_top( Win_main );
  341.  
  342.     /* Tell all subtasks to proceed */
  343.     for( i = 0; i < SlaveC; ++i )
  344.     mal_addto( Slavetbl[i].sd_malhan, NULL, 0, MSG_GO );
  345.  
  346.     /* Wait for the test period */
  347.     tim_addto( Tim_main, Gotime * 100 );
  348.     tim_read( Tim_main );
  349.  
  350.     /* Tell all tasks to stop */
  351.     for( i = 0; i < SlaveC; ++i )
  352.     mal_addto( Slavetbl[i].sd_malhan, NULL, 0, MSG_STOP );
  353.  
  354.     /* Get results from all subtasks */
  355.     for( ; ; ) {
  356.     msgcode = mal_read( Mal_main, &msgP, &msgL );
  357.     if ( msgcode == MSG_REPORT ) {
  358.         sendtsk = mal_addr( Mal_main );
  359.         for( i = 0, slaveP = &Slavetbl[0], doneC = 0;
  360.              i < SlaveC; ++i, ++slaveP ) {
  361.         if ( sendtsk == slaveP->sd_apphan ) {
  362.             slaveP->sd_doneF = TRUE;
  363.             memcpy( &slaveP->sd_rsmsg, msgP, sizeof(RSMSG) );
  364.         }
  365.         if ( slaveP->sd_doneF )
  366.             ++doneC;
  367.         }
  368.  
  369.         /* If all tasks are done, proceed to next phase */
  370.         if ( doneC == SlaveC )
  371.         break;
  372.     }
  373.     }
  374.  
  375.     /* Generate report */
  376.     report();
  377. }
  378.  
  379.  
  380.  
  381.  
  382. /* Report the results of the run */
  383. report()
  384. {
  385.     int        i;
  386.     float        alltime;
  387.     float        readtime;
  388.     float        writetime;
  389.     float        cputime;
  390.     FILE        *rfP;        /* Report file ptr */
  391.     CNMSG        *cP;
  392.     RSMSG        *rP;
  393.  
  394.     if ( ( rfP = fopen( &Gofile[0], "a" ) ) == NULL )
  395.     if ( ( rfP = fopen( &Gofile[0], "w" ) ) == NULL ) {
  396.         beep();
  397.         return;
  398.     }
  399.  
  400.     fprintf( rfP, "\n\n" );
  401.     for( i = 0; i < SlaveC; ++i ) {
  402.         cP = &(Slavetbl[i].sd_cnmsg);
  403.     rP = &(Slavetbl[i].sd_rsmsg);
  404.     alltime = ((float)rP->rm_alltime)/(float)rP->rm_tick;
  405.     readtime = ((float)rP->rm_readtime)/(float)rP->rm_tick;
  406.     writetime = ((float)rP->rm_writetime)/(float)rP->rm_tick;
  407.     cputime = ((float)rP->rm_cputime)/(float)rP->rm_tick;
  408.     fprintf( rfP, "Task %d\n", i );
  409.     fprintf( rfP, "  Configuration:\n" );
  410.     fprintf( rfP, "    fsize=%ld   xsize=%d   bufC=%d   ioC=%d\n",
  411.            cP->cm_fsize, cP->cm_xsize, cP->cm_iobufC, cP->cm_ioC );
  412.     fprintf( rfP, "    read=%s   write=%s  method=%s\n",
  413.             cP->cm_readF?"TRUE":"FALSE",
  414.             cP->cm_writeF?"TRUE":"FALSE",
  415.             cP->cm_seqF?"SEQUENTIAL":"RANDOM" );
  416.     fprintf( rfP, "    cpuC=%ld   sleep=%ld\n",
  417.              cP->cm_cpuC, cP->cm_sleep );
  418.     fprintf( rfP, "  Results:\n" );
  419.     fprintf( rfP, "    loops=%ld\n", rP->rm_loopC );
  420.     fprintf( rfP, "    total time=%f\n", alltime );
  421.         if ( ( cP->cm_readF || cP->cm_writeF ) &&
  422.          ( cP->cm_ioC != 0 ) ) {
  423.         if ( cP->cm_readF ) {
  424.         fprintf( rfP, "    read time=%f\n", readtime );
  425.         }
  426.         if ( cP->cm_writeF ) {
  427.         fprintf( rfP, "    write time=%f\n", writetime );
  428.         }
  429.     }
  430.     else
  431.         fprintf( rfP, "    <no I/O>\n" );
  432.  
  433.     fprintf( rfP, "    cpu time=%f\n", cputime );
  434.     }
  435.  
  436.     fclose( rfP );
  437. }
  438.  
  439.  
  440.  
  441.  
  442. /* getgo() -- Get execution parameters */
  443.  
  444. int
  445. getgo()
  446. {
  447.     char        field;        /* Field selected */
  448.     char        done;
  449.     int        i;
  450.     int        fsize;
  451.     int        tsize;
  452.     int        kbdstat;
  453.     int        kbdL;        /* Length of keyboard input */
  454.     int        row, col;    /* Current cursor pos */
  455.     char        *kbdP;        /* Ptr to keyboard buffer */
  456.     char        *fieldP;    /* Ptr to field definition */
  457.     char        fieldbuf[50];    /* Buffer for field value */
  458.  
  459.     /* Allocate a window */
  460.     Win_go = win_new( "Execution", 15, 12, 60 );
  461.     win_logattr( Win_go, 1 );
  462.     win_attr( Win_go, 1 );
  463.     win_erase( Win_go );
  464.  
  465.     /* Make its keyboard object and attach to the window */
  466.     Kbd_go = key_new();
  467.     key_open( Kbd_go, Win_go );
  468.  
  469.     /* Enable field mode with cursor */
  470.     key_addto( Kbd_go, KBF_FIELD+KBF_CURSOR );
  471.  
  472.     /* Throw up the go menu */
  473.     win_swrite( Win_go, &Gomenu[0] );
  474.  
  475.     /* Send out the field info */
  476.     win_stream( Win_go, &Goftab[0] );
  477.  
  478.     /* Highlight the field entry areas && initialize field data */
  479.     for( field = 1, fieldP = &Goftab[FTABBASE+6];
  480.         field < GO_FIELDC; ++field, fieldP += 8 ) {
  481.     if ( ( fieldP[4] & (FTE_INPUT|FTE_SELECT) ) == FTE_INPUT )
  482.         field_highlight( Win_go, &Goftab[0], field, ATTR_REVERSE );
  483.     }
  484.  
  485.     /* Set defaults */
  486.     Gotime = 10L;            /* 10 seconds */
  487.     strcpy ( &Gofile[0], "dt.rep" );    /* Filename */
  488.  
  489.     /* Make the window visible */
  490.     win_move( Win_go, 3, 10 );
  491.     win_unhide( Win_go );
  492.     win_top( Win_go );
  493.  
  494.     /* Loop processing menu items */
  495.     fld_cursor( Win_go, 1 );
  496.     for( done = 0; done == 0; ) {
  497.     key_read( Kbd_go, &kbdP, &kbdL );
  498.     kbdstat = key_status( Kbd_go );
  499.  
  500.     if ( kbdstat != 1 ) {
  501.         beep();
  502.         continue;
  503.     }
  504.  
  505.     /* get current cursor position */
  506.     qry_cursor( Win_go, &row, &col );
  507.  
  508.     /* Process the field(s) */
  509.     for( ; kbdL > 0; kbdP += tsize, kbdL -= tsize ) {
  510.         field = *kbdP;
  511.         fsize = *(int *)(kbdP+1);
  512.         fieldP = kbdP + sizeof(int) + 1;
  513.         tsize = fsize + sizeof(int) + 1;
  514.         memcpy( &fieldbuf[0], fieldP, fsize );
  515.         fieldbuf[fsize] = '\0';
  516.  
  517.         switch( field ) {
  518.             case    GO_TIME:    /* Execution time */
  519.             Gotime = atol( &fieldbuf[0] );
  520.             break;
  521.  
  522.         case    GO_FILENAME:
  523.             strcpy( &Gofile[0], &fieldbuf[0] );
  524.             for( i = 0; ; ++i )
  525.             if ( Gofile[i] == ' ' ) {
  526.                 Gofile[i] = '\0';
  527.                 break;
  528.             }
  529.             break;
  530.  
  531.         case    GO_ABORT:    /* Abort request */
  532.             done = -1;
  533.             break;
  534.  
  535.         case    GO_CONFIRM:    /* Confirmed exit */
  536.             done = 1;
  537.             break;
  538.  
  539.         default:
  540.             break;
  541.         }
  542.     }
  543.  
  544.     /* Restore cursor */
  545.     win_cursor( Win_go, row, col );
  546.     }
  547.  
  548.     /* Close the objects used in this interaction */
  549.     key_free( Kbd_go );
  550.     win_free( Win_go );
  551.     return( done == 1 );
  552. }
  553.  
  554.  
  555. /* Program configuration menu -- configure a new set of progs */
  556.  
  557. task_def()
  558. {
  559.     char        field;        /* Field selected */
  560.     char        done;
  561.     int        i;
  562.     int        fsize;
  563.     int        tsize;
  564.     int        kbdstat;
  565.     int        kbdL;        /* Length of keyboard input */
  566.     int        row, col;    /* Current cursor pos */
  567.     char        *kbdP;        /* Ptr to keyboard buffer */
  568.     char        *fieldP;    /* Ptr to field definition */
  569.     char        fieldbuf[20];    /* Buffer for field value */
  570.  
  571.     /* Allocate a window */
  572.     Win_tdef = win_new( "Task Definition", 15, 12, 60 );
  573.     win_logattr( Win_tdef, 1 );
  574.     win_attr( Win_tdef, 1 );
  575.     win_erase( Win_tdef );
  576.  
  577.     /* Make its keyboard object and attach to the window */
  578.     Kbd_tdef = key_new();
  579.     key_open( Kbd_tdef, Win_tdef );
  580.  
  581.     /* Enable field mode with cursor */
  582.     key_addto( Kbd_tdef, KBF_FIELD+KBF_CURSOR );
  583.  
  584.     /* Throw up the tdef menu */
  585.     win_swrite( Win_tdef, &Tdefmenu[0] );
  586.  
  587.     /* Send out the field info */
  588.     win_stream( Win_tdef, &Tdefftab[0] );
  589.  
  590.     /* Highlight the field entry areas && initialize field data */
  591.     for( field = 1, fieldP = &Tdefftab[FTABBASE+6];
  592.          field < TDF_FIELDC;
  593.          ++field, fieldP += 8 ) {
  594.     Tdf_valid[field] = FALSE;
  595.     Tdf_fields[field][0] = '\0';
  596.     if ( ( fieldP[4] & (FTE_INPUT|FTE_SELECT) ) == FTE_INPUT )
  597.         tdef_highlight( field, ATTR_REVERSE );
  598.     }
  599.  
  600.     /* Mark certain fields as valid */
  601.     Tdf_valid[TDF_READ] = TRUE;
  602.     Tdf_valid[TDF_WRITE] = TRUE;
  603.     Tdf_valid[TDF_SEQ] = TRUE;
  604.     Tdf_valid[TDF_RAND] = TRUE;
  605.     Tdf_valid[TDF_CONFIRM] = TRUE;
  606.     Tdf_valid[TDF_ABORT] = TRUE;
  607.  
  608.     /* Make the window visible */
  609.     win_move( Win_tdef, 3, 10 );
  610.     win_unhide( Win_tdef );
  611.     win_top( Win_tdef );
  612.  
  613.     /* Select SEQUENTIAL I/O */
  614.     radio_button( Win_tdef, TDF_SEQ, TDF_RAND, TDF_SEQ );
  615.     Tdf_fields[TDF_SEQ][0] = 'Y';
  616.     Tdf_fields[TDF_RAND][0] = 'N';
  617.     fld_cursor( Win_tdef, 1 );
  618.  
  619.     /* Loop processing menu items */
  620.     for( done = 0; done == 0; ) {
  621.     key_read( Kbd_tdef, &kbdP, &kbdL );
  622.     kbdstat = key_status( Kbd_tdef );
  623.  
  624.     if ( kbdstat != 1 ) {
  625.         beep();
  626.         continue;
  627.     }
  628.  
  629.     /* get current cursor position */
  630.     qry_cursor( Win_tdef, &row, &col );
  631.  
  632.     /* Process the field(s) */
  633.     for( ; kbdL > 0; kbdP += tsize, kbdL -= tsize ) {
  634.         field = *kbdP;
  635.         fsize = *(int *)(kbdP+1);
  636.         fieldP = kbdP + sizeof(int) + 1;
  637.         tsize = fsize + sizeof(int) + 1;
  638.         memcpy( &fieldbuf[0], fieldP, fsize );
  639.         fieldbuf[fsize] = '\0';
  640.  
  641.         switch( field ) {
  642.         case    TDF_TSIZE:    /* Task size */
  643.             tdnum_valid( field, &fieldbuf[0], 20L, 1000L );
  644.             break;
  645.  
  646.         case    TDF_SLEEP:    /* Sleep interval */
  647.             tdnum_valid( field, &fieldbuf[0], 0L, 1000L );
  648.             break;
  649.  
  650.         case    TDF_READ:    /* I/O read */
  651.         case    TDF_WRITE:    /* I/O Write */
  652.             fld_type( Win_tdef, field,
  653.             (*fieldP=='Y')?FLT_SELECT : FLT_DESELECT );
  654.  
  655.             Tdf_fields[field][0] = *fieldP;
  656.             break;
  657.  
  658.         case    TDF_SEQ:    /* Sequential I/O */
  659.         case    TDF_RAND:    /* Random I/O */
  660.             radio_button( Win_tdef, TDF_SEQ, TDF_RAND, field );
  661.             Tdf_fields[TDF_SEQ][0] = (field==TDF_SEQ ? 'Y' : 'N' );
  662.             Tdf_fields[TDF_RAND][0] = (field==TDF_RAND ? 'Y' : 'N' );
  663.             break;
  664.  
  665.         case    TDF_FSIZE:    /* File size */
  666.             tdnum_valid( field, &fieldbuf[0], 10L, 5000L );
  667.             break;
  668.  
  669.         case    TDF_XSIZE:    /* Transfer size */
  670.             tdnum_valid( field, &fieldbuf[0], 512L, 8192L );
  671.             break;
  672.  
  673.         case    TDF_BUFC:    /* Buffers */    
  674.             tdnum_valid( field, &fieldbuf[0], 1L, 10L );
  675.             break;
  676.  
  677.         case    TDF_IOC:    /* I/O loops */
  678.             tdnum_valid( field, &fieldbuf[0], 0L, 10000L );
  679.             break;
  680.  
  681.         case    TDF_LOOPC:    /* CPU loops */
  682.             tdnum_valid( field, &fieldbuf[0], 0L, 5000000L );
  683.             break;
  684.  
  685.         case    TDF_TASKC:    /* Number of tasks */
  686.             tdnum_valid( field, &fieldbuf[0], 1L,
  687.                   (long)(MAXSLAVES-SlaveC) );
  688.             break;
  689.  
  690.         case    TDF_ABORT:    /* Abort request */
  691.             done = -1;
  692.             break;
  693.  
  694.         case    TDF_CONFIRM:    /* Confirmed exit */
  695.             done = 1;        /* Pretend we can leave */
  696.  
  697.             /* Now go through and look for invalidated fields */
  698.             for( i = TDF_FIELDC-1; i > 0; --i )
  699.             if ( !Tdf_valid[i] ) {
  700.                 done = 0;
  701.                 tdef_highlight( i, ATTR_ERROR );
  702.                 fld_cursor( Win_tdef, i );
  703.             }
  704.             
  705.             break;
  706.  
  707.         default:
  708.             break;
  709.         }
  710.     }
  711.  
  712.     /* Restore cursor */
  713.     win_cursor( Win_tdef, row, col );
  714.     }
  715.  
  716.     /* Close the objects used in this interaction */
  717.     key_free( Kbd_tdef );
  718.     win_free( Win_tdef );
  719.  
  720.     /* Add slave configuration information if exited with confirm */
  721.     if ( done == 1 )
  722.     tdef_add();
  723.  
  724. }
  725.  
  726.  
  727. /* Add slave configurations from most recent task definition menu */
  728. tdef_add()
  729. {
  730.     int        i;        /* Scratch */
  731.     CNMSG        *cnmsgP;    /* Ptr to config message */
  732.  
  733.     /* Define slave configuration information */
  734.     for( i = atoi( &Tdf_fields[TDF_TASKC][0] ); i > 0; --i, ++SlaveC ) {
  735.     cnmsgP = &Slavetbl[SlaveC].sd_cnmsg;
  736.  
  737.     cnmsgP->cm_taskN = SlaveC;
  738.     cnmsgP->cm_ioC = atoi( &Tdf_fields[TDF_IOC][0] );
  739.     cnmsgP->cm_fsize = atol( &Tdf_fields[TDF_FSIZE][0] ) * 1024;
  740.     cnmsgP->cm_xsize = atoi( &Tdf_fields[TDF_XSIZE][0] );
  741.     cnmsgP->cm_iobufC = atoi( &Tdf_fields[TDF_BUFC][0] );
  742.     cnmsgP->cm_readF = (Tdf_fields[TDF_READ][0] == 'Y');
  743.     cnmsgP->cm_writeF = (Tdf_fields[TDF_WRITE][0] == 'Y');
  744.     cnmsgP->cm_seqF = (Tdf_fields[TDF_SEQ][0] == 'Y');
  745.     cnmsgP->cm_cpuC = atol( &Tdf_fields[TDF_LOOPC][0] );
  746.     cnmsgP->cm_sleep = atol( &Tdf_fields[TDF_SLEEP][0] );
  747.     }
  748.  
  749.  
  750.  
  751. /* tdnum_valid -- valid numerical field return for task definition */
  752. tdnum_valid( field, bufP, minval, maxval )
  753.     int        field;        /* Field number */
  754.     char        *bufP;        /* Returned value */
  755.     long        minval;        /* Minimum allowable */
  756.     long        maxval;        /* Maximum allowable */
  757. {
  758.     int        sign;
  759.     long        val;        /* Accumulator. */
  760.  
  761.     /* Strip leading spaces */
  762.     while( *bufP == ' ' )
  763.     ++bufP;
  764.  
  765.     /* Store the field string */
  766.     strcpy( &Tdf_fields[field][0], bufP );
  767.  
  768.     sign = 1;
  769.     val = 0;
  770.  
  771.     if ( *bufP == '-' ) {
  772.     sign = -1;
  773.     ++bufP;
  774.     }
  775.  
  776.     for( ; *bufP != '\0'; ++bufP ) {
  777.     if ( ( *bufP < '0' ) || ( *bufP > '9' ) ) {
  778.         Tdf_valid[field] = FALSE;
  779.         return;
  780.     }
  781.     val = val*10 + (*bufP - '0');
  782.     }
  783.  
  784.     val = val * sign;
  785.     if ( ( val < minval ) || ( val > maxval ) )
  786.     Tdf_valid[field] = FALSE;
  787.     else {
  788.     Tdf_valid[field] = TRUE;
  789.     tdef_highlight( field, ATTR_REVERSE );
  790.     }
  791. }
  792.  
  793. /* Radio button processing -- light only one button of a group. */
  794.  
  795. radio_button( win, first, last, chosen )
  796.     ULONG        win;        /* The window */
  797.     int        first;        /* First of set */
  798.     int        last;        /* Last of set */
  799.     int        chosen;        /* The one selected */
  800. {
  801.     int        i;        /* Scratch */
  802.  
  803.     for( i = first; i <= last; ++i )
  804.     fld_type( win, i, (i == chosen) ? FLT_SELECT : FLT_DESELECT );
  805. }
  806.  
  807.  
  808. /* Highlight a field in the task definition menu */
  809. tdef_highlight( field, attr )
  810.     int        field;        /* Field to highlight */
  811.     int        attr;        /* Attribute to use */
  812. {
  813.     field_highlight( Win_tdef, &Tdefftab[0], field, attr );
  814. }
  815.  
  816.  
  817.  
  818. /* Highlight a field within a menu */
  819.  
  820. field_highlight( win, ftabP, field, attr )
  821.     ULONG        win;        /* Window handle */
  822.     char        *ftabP;        /* Ptr to field table */
  823.     int        field;        /* Which field */
  824.     int        attr;        /* Attribute to use */
  825. {
  826.     /* Skip over the field overhead */
  827.     ftabP += FTABBASE+6;
  828.  
  829.     /* Skip to the particular field */
  830.     ftabP += (field-1)*8;
  831.  
  832.     /* Highlight the field area */
  833.     win_cursor( Win_tdef, ftabP[0], ftabP[1] );
  834.     win_repattr( Win_tdef, ftabP[3]-ftabP [1]+1, attr );
  835. }
  836.